package com.jichangxiu.framework.config;

import com.jichangxiu.common.properties.JcxProperties;
import com.jichangxiu.common.utils.IpUtils;
import com.jichangxiu.framework.filter.XssFilter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.util.PathMatcher;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import javax.annotation.Resource;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

/**
 * FrameworkConfig:
 *
 * @author Jcx
 * @create 2023-04-04 13:03
 */
@Slf4j
@Configuration
@EnableConfigurationProperties({JcxProperties.class})
public class FrameworkConfig implements WebMvcConfigurer, CommandLineRunner {

    @Value("${spring.application.name:Jcx-Boot}")
    private String applicationName;

    @Value("${server.port:8080}")
    private String port;

    @Value("${server.servlet.context-path:/}")
    private String path;

    @Value("${spring.profiles.active:dev}")
    private String active;

    @Resource
    private JcxProperties jcxProperties;

    @Bean
    public CorsFilter corsFilter() {
        log.info("加载 cors 配置");
        final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        final CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.setAllowCredentials(true);
        corsConfiguration.addAllowedHeader("*");
        corsConfiguration.addAllowedOriginPattern("*");
        corsConfiguration.addAllowedMethod("*");
        source.registerCorsConfiguration("/**", corsConfiguration);
        return new CorsFilter(source);
    }

    @Bean
    @ConditionalOnProperty(value = "jcx.Security-Properties.xss-enabled", havingValue = "true")
    public FilterRegistrationBean<XssFilter> xssFilter(JcxProperties jcxProperties, PathMatcher pathMatcher) {
        log.info("加载 xss 配置");
        FilterRegistrationBean<XssFilter> bean = new FilterRegistrationBean<>();
        bean.setFilter(new XssFilter(jcxProperties, pathMatcher));
        bean.setOrder(Integer.MAX_VALUE);
        bean.setName("xssFilter");
        return bean;
    }

    @Override
    public void run(String... args) throws Exception {
        log.info("Jcx-Boot 框架 FrameworkConfig 开始打印启动信息");
        // 打印信息
        String str = "\n------------- " + applicationName + " (" + active + ") 启动成功 --by "
                + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())
                + " -------------\n" + "\t- Local:   http://localhost:" + port + path
                + "\n" + "\t- Local2:  http://127.0.0.1:" + port + path
                + "\n" + "\t- Network: http://" + IpUtils.getHostIp() + ":" + port + path + "\n";
        System.out.println(str);
    }

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        log.info("去除 String 消息处理器");
        // 移除 String 消息处理器不然返回自定义的对象会有问题
        converters.removeIf(httpMessageConverter -> httpMessageConverter.getClass() == StringHttpMessageConverter.class);
    }

    /**
     * 本地文件上传路径
     *
     * @param registry 配置
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        String path = jcxProperties.getFileProperties().getRootFolder() + File.separator;
        log.info("本地文件挂载：" + path);
        registry.addResourceHandler("/" + jcxProperties.getFileProperties().getActionPrefix() + "/**")
                .addResourceLocations("file:" + path);
    }

}
